<?php
	
	include "include.php";

	class RequestFilter {
		
		private $currentUrl;
		private $currentPath;
		private $hasAction;
		private $action;
		private $hasMethod;
		private $method;
		private $applicationContext;
		private $viewPackage;
		private $templatePackage;
		private $allowedExtensions;
		private $configuration;
		
		public function __construct() {
			Logger::debug($this, "Interceptando requisicao");
			$this->applicationContext = Config::getApplicationContext();
			$this->viewPackage = $this->getConfiguration("view-package");
			$this->templatePackage = $this->getConfiguration("template-package");
			$this->currentUrl = parse_url($_SERVER['REQUEST_URI']);
			$this->hasAction = false;
			$this->hasMethod = false;
			$this->allowedExtensions = array('.gif','.jpg','.css','.js');
			$this->process();
		}

		public function getConfiguration($name) {
			if( !$this->configuration ) $this->configuration = Config::getConfig("configuration");
			
			if( isset($this->configuration[$name]) ) return $this->configuration[$name];
			else die("Configuration '$name' not found");
		}
		
		public function process() {
			//$this->currentPath = $this->currentUrl[path];
			
			foreach ($this->currentUrl as $key => $value) {
				if( $key == "path" ) {
					$this->currentPath = $value;
				}
			}
			
			Logger::debug($this, "Executando o motodo process para '" . $this->currentPath . "'");
			
			foreach ( $this->allowedExtensions as $extension ) {
				if( strpos($this->currentPath, $extension) > -1 ) {
					Logger::debug($this, "A requisicao e para um recurso permitido : " . $this->currentPath);
					//require $this->currentPath;
					return;
				}
			}				
			
			if( $this->applicationContext != "" && strpos($this->currentPath, $this->applicationContext) > -1 ) {
				$this->currentPath = substr($this->currentPath, strlen($this->applicationContext), strlen($this->currentPath));
			}
			Logger::debug($this, "Setando o currentPath : $this->currentPath");
						
			$token = split('/', $this->currentPath);
			
			$this->setAction();
			$this->setMethod();			

			if( $this->hasAction && $this->hasMethod ) {
				$params = array();

				for ($index = 2; $index < sizeof($token); $index++) {
					$params[] = $token[$index];
					Logger::debug($this, "Adicionando parametro a requisicao : " . $token[$index]);
				}
				
				Scope::putDefaultParameters($params);
			}
			
			
			if( sizeof($token) == 0 || $token[0] == "" ) { // welcome.php
				$this->dispatch('welcome.php');
			} else if( sizeof($token) == 1 && $token[0] != "" ) { // Has a page
				$page = $this->viewPackage . "/" . $token[0]; 
				
				if( file_exists($page) && !is_dir($page) ) {
					$this->dispatch($page);
				} else if( file_exists($page . ".php") ) {
					$this->dispatch($page . ".php");
				} else if( is_dir($page) && file_exists($page . "/index.php") ) {
					$this->dispatch($page . "/index.php");
				} else {
					$this->dispatch('error.php');
				}
			} else if( sizeof($token) >= 2 ) {
				if( $this->hasAction && $this->hasMethod ) {
					$methodName = (string)$this->method;
					$this->action->$methodName(); 	
				}			
				
				$page = $this->viewPackage . "/" . $this->currentPath;
								
				if( file_exists($page) && !is_dir($page) ) {
					Logger::debug($this, "Pagina encontrada. Dispatch efetuado para '$page'");
					$this->dispatch($page);
				} else if( file_exists($page . ".php")) {
					Logger::debug($this, "Pagina encontrada. Dispatch efetuado para '$page'");
					$this->dispatch($page . ".php");	
				} else if( $this->hasAction && $this->hasMethod ) { // houve execu��o mas n�o existe pagina, volta para a anterior
					$lastPage = Scope::loadSessionVar("LAST_PAGE");
					if( $lastPage != null && $lastPage != "" ) {
						Logger::debug($this, "Metodo executado, mas nao existe pagina de dispatch. Volto para a pagina anterior");
						$this->dispatch($lastPage);	
					} else {
						Logger::debug($this, "Metodo executado, mas nao existe pagina de dispatch. Last_Page ainda nao setado, vou para 'error.php'");
						$this->dispatch('error.php');
					}					
				} else {
					Logger::debug($this, "Erro ao efetuar o dispatch");
					$this->dispatch('error.php');
				}				
			}						
		}
		
		private function setMethod() {
			try { 
				Logger::debug($this, "Executando o metodo setMethod '" . $this->currentPath . "'");
				$token = split('/', $this->currentPath);
				$this->method = $token[1];
				if( $this->method != "" ) {
					if( strpos($this->method, ".php") > 0 ) {
						$this->method = substr($this->method,0,strpos($this->method,".php"));
					}
					
					if( $this->action != null && $this->action != "" ) {
						$methods = ReflectionUtils::getMethods($this->action);
						
						foreach($methods as $methodname) {
							if( $methodname == $this->method ) {
								$this->hasMethod = true;
								break;	
							}
						}
					}
					
					if( $this->hasMethod ) {
						Logger::debug($this, "Metodo $this->method encontrado");	
					} else {
						Logger::debug($this, "Metodo $this->method nao encontrado");
					}
				}
			} catch(Exception $e) { }			
		}
		
		private function setAction() {
			Logger::debug($this, "Executando o metodo setAction para '" . $this->currentPath . "'");
			try {
				$token = split('/', $this->currentPath);
				$this->action = $token[0];
				
				if( $this->action != "" ) {
					$this->action = ucfirst($this->action) . "Action";
					Logger::debug($this, "Action $this->action encontrado");
					$this->action = new $this->action();
					$this->hasAction = true;
				}	
			} catch(Exception $e) { }
		} 
		
		private function dispatch($value) {
			Logger::debug($this, "Efetuando o dispatch para $value");
			Scope::putRequestVar("TEMPLATE_BODY", $value);
			Scope::putSessionVar("LAST_PAGE", $value);
			require $this->templatePackage . "/main.php";
			return;
		}
	}
	
	Config::setRoot(realpath("."));
	
	new RequestFilter();
?>